var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spread = (this && this.__spread) || function () {
    for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
    return ar;
};
import { createStore } from "./store";
import { AutoInject } from "./inject";
import { provideMethodName } from "./utils";
var StoreEmitter = (function () {
    function StoreEmitter(storeItem) {
        this.storeItem = storeItem;
    }
    StoreEmitter.prototype.emit = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        this.storeItem.forEach(function (item) {
            var _a;
            if (item.value["target"] && item.value["propertyKey"]) {
                var target = item.value["target"];
                var propertyKey = item.value["propertyKey"];
                if (target[propertyKey] !== undefined) {
                    (_a = target[propertyKey]).call.apply(_a, __spread([target], args));
                }
            }
        });
    };
    return StoreEmitter;
}());
export { StoreEmitter };
var EventController = (function () {
    function EventController(store) {
        this.store = store;
    }
    EventController.prototype.emit = function () {
        var _a;
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return (_a = this.emitHook()).emit.apply(_a, __spread(args));
    };
    EventController.prototype.getStore = function () {
        return this.store;
    };
    EventController.prototype.includeTags = function (tag) {
        var checkTags = function (tagName) {
            if (typeof tag === "string") {
                return typeof tagName === "string" && tagName.includes(tag);
            }
            else {
                return typeof tagName === "string" && tag.includes(tagName);
            }
            return false;
        };
        var items = this.store.items.filter(function (item) {
            if (item.value.tag !== undefined) {
                return checkTags(item.value.tag);
            }
            return false;
        });
        return this.emitHook(items);
    };
    EventController.prototype.selectTags = function (tag) {
        var checkTags = function (tagName) {
            if (typeof tag === "string" || typeof tag === "object") {
                return tagName === tag;
            }
            else {
                return tag(tagName);
            }
        };
        var items = this.store.items.filter(function (item) {
            if (item.value.tag !== undefined) {
                return checkTags(item.value.tag);
            }
            return false;
        });
        return this.emitHook(items);
    };
    EventController.prototype.emitHook = function (items) {
        return new StoreEmitter(items
            ? items
            : this.store.items.filter(function (item) { return item.value.tag !== undefined; }));
    };
    return EventController;
}());
export { EventController };
var EventInjector = (function () {
    function EventInjector() {
        var _this = this;
        this.Subject = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            return function (target) {
                var newTarget = AutoInject.apply(void 0, __spread([target], args));
                for (var i in _this.controller.getStore().items) {
                    var item = _this.controller.getStore().items[i];
                    if (item.value.target !== undefined &&
                        item.value.target.constructor !== undefined &&
                        item.value.propertyKey !== undefined &&
                        item.value.tag !== undefined) {
                        if (String(item.value.target.constructor) === String(target)) {
                            item.value.target = newTarget;
                        }
                    }
                }
            };
        };
        this.Provide = function () {
            return function (target, propertyKey, descriptor) {
                _this.store.add({
                    name: provideMethodName(target, propertyKey, descriptor),
                    value: {
                        target: target,
                        propertyKey: propertyKey,
                        tag: null
                    }
                });
            };
        };
        this.Tag = function (tag) {
            return function (target, propertyKey, descriptor) {
                var storeItemName = provideMethodName(target, propertyKey, descriptor);
                var noHashGetItem = _this.controller
                    .getStore()
                    .get(storeItemName, false);
                if (noHashGetItem.tag !== undefined) {
                    noHashGetItem.tag = tag || null;
                }
            };
        };
        this.store = createStore();
        this.controller = new EventController(this.store);
    }
    return EventInjector;
}());
export { EventInjector };
export function createEvent() {
    return new EventInjector();
}
